/*
 * file:  expr.cpp (implementation of Expr).
 * Author: Jeremy Johnson 
 * Date: 1/31/06
 *
 * Description: 
 */

#include <iostream>
#include <string>
#include <map>
#include <list>
#include "program.h"

using namespace std;


Program::Program(StmtList *SL)
{
SymbolTable_.clear();
SL_ = SL;
}

void Program::dump() 
{
  map<string,int>::iterator p;

  cout << "Dump of Symbol Table" << endl;
  for (p = SymbolTable_.begin();p != SymbolTable_.end();p++)
    cout << p->first << " -> " << p->second << endl;
}

void Program::eval() 
{
	SL_->eval(SymbolTable_);
}


void StmtList::insert(Stmt * S)
{
  SL_.push_front(S);
}

void StmtList::eval(map<string,int> &T) 
{
  list<Stmt*>::iterator Sp;
  for (Sp = SL_.begin();Sp != SL_.end();Sp++)
	(*Sp)->eval(T);
}

AssignStmt::AssignStmt(string name, Expr *E)
{
  name_ = name;
  E_ = E;
}

void AssignStmt::eval(map<string,int> &T) const
{
	T[name_] = E_->eval(T);
}

IfStmt::IfStmt(Expr *E, StmtList *S1, StmtList *S2)
{
  E_ = E;
  S1_ = S1;
  S2_ = S2;
}

void IfStmt::eval(map<string,int> &T) const
{
	if (E_->eval(T) > 0)
		S1_->eval(T);
	else
		S2_->eval(T);
}

WhileStmt::WhileStmt(Expr *E, StmtList *S)
{
  E_ = E;
  S_ = S;
}

void WhileStmt::eval(map<string,int> &T) const
{
	while (E_->eval(T) > 0) 
		S_->eval(T);
}

Number::Number(int value)
{
	value_ = value;
}

int Number::eval(map<string,int> T) const
{
	return value_;
}

Ident::Ident(string name)
{
	name_ = name;
}

int Ident::eval(map<string,int> T) const
{
	return T[name_];
}

Plus::Plus(Expr* op1, Expr* op2)
{
	op1_ = op1;
	op2_ = op2;
}

int Plus::eval(map<string,int> T) const
{
	return op1_->eval(T) + op2_->eval(T);
}

Minus::Minus(Expr* op1, Expr* op2)
{
	op1_ = op1;
	op2_ = op2;
}

int Minus::eval(map<string,int> T) const
{
	return op1_->eval(T) - op2_->eval(T);
}

Times::Times(Expr* op1, Expr* op2)
{
	op1_ = op1;
	op2_ = op2;
}

int Times::eval(map<string,int> T) const
{
	return op1_->eval(T) * op2_->eval(T);
}
